/**
 * 
 */
package edu.acatlan.unam.shared.bdoo;

//Librerías de la clase
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.CssColor;

/**
 * @author jacobo
 *
 */
@SuppressWarnings("serial")
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class TTabla implements Serializable, ModeloRelacional, ElementoGrafico {
	//Propiedades de la clase
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Long idTabla;
	@Persistent
	private String nombreTb;
	@Persistent
	private Long idEsquema;
	@Persistent
	private Integer posX;
	@Persistent
	private Integer posY;
	@NotPersistent
	private ArrayList<TColumna> columnas;
	@NotPersistent
	private ArrayList<TRelacion> relaciones;
	@NotPersistent
	private boolean isSelected;
		
	/**
	 * Constructor predeterminado
	 */
	public TTabla() {
	
	}
		
	/**
	 * @param nombreTb indica el nombre de la tabla
	 * @param idEsquema indica el esquema de base de datos al que pertenece
	 * @param posX indica la posición en X en el lienzo
	 * @param posY indica la posición en Y en el lienzo
	 */
	public TTabla(String nombreTb, Long idEsquema, int posX, int posY) {
		this.nombreTb = nombreTb;
		this.idEsquema = idEsquema;
		this.posX = new Integer(posX);
		this.posY = new Integer(posY);
		columnas = new ArrayList<TColumna>();
		relaciones = new ArrayList<TRelacion>();
	}

	/**
	 * @return the idTabla
	 */
	public Long getIdTabla() {
		return idTabla;
	}

	/**
	 * @param idTabla the idTabla to set
	 */
	public void setIdTabla(Long idTabla) {
		this.idTabla = idTabla;
	}

	/**
	 * @return the nombreTb
	 */
	public String getNombreTb() {
		return nombreTb;
	}

	/**
	 * @param nombreTb the nombreTb to set
	 */
	public void setNombreTb(String nombreTb) {
		this.nombreTb = nombreTb;
	}

	/**
	 * @return the idEsquema
	 */
	public Long getIdEsquema() {
		return idEsquema;
	}

	/**
	 * @param idEsquema the idEsquema to set
	 */
	public void setIdEsquema(Long idEsquema) {
		this.idEsquema = idEsquema;
	}

	/* (non-Javadoc)
	 * @see edu.acatlan.unam.shared.bdoo.ModeloRelacional#getCadenaDLL()
	 */
	public String getCadenaDLL() {
		String cad = "`" + nombreTb + "` (<br/>";
		ArrayList<String> pk = new ArrayList<String>();
		
		//Agregar las columnas
		for(TColumna c : columnas) {
			cad += c.getCadenaDLL() + " ,<br/>";
			
			if(c.getEsLlave())
				pk.add(c.getNombreCol());
		}
		
		//Crear la llave primaria
		if(pk.size() > 0) {
			cad += "PRIMARY KEY (";
			for(String p : pk)
				cad += "'" + p + "', ";
			cad = cad.substring(0, cad.length() - 2) + ") ,<br/>";
		}
		
		//Indicar las relaciones (CONSTRAINT'S). 
		for(TRelacion r: relaciones)
			cad += r.getCadenaDLL() + " ,<br/>";
		cad = cad.substring(0, cad.length() - 7);
		cad += ")<br/>ENGINE = InnoDB;<br/>";
		
		//Crear los índices
		for(int i = 0; i < relaciones.size(); i++) {
			cad += "CREATE INDEX '" + relaciones.get(i).getNombreRelacion() + "' ON '" + nombreTb + "' (";
			Iterator<Entry<String, String>> it = relaciones.get(i).getNomColumnas().entrySet().iterator();
			
			while(it.hasNext()) {
				//Indicamos las columnas que conforman el índice.
				Map.Entry<String, String> e = (Map.Entry<String, String>)it.next();
				cad += "'" + e.getKey() + "', ";
			}
			
			cad = cad.substring(0, cad.length() - 3) + ")<br/>";
		}
		
		//Creamos los índices únicos
		for(TColumna c : columnas)
			if(c.getEsUnico())
				cad += "CREATE UNIQUE INDEX '" + c.getNombreCol() + "_UNIQUE' ON '" + nombreTb + "' ('" + c.getNombreCol() + "' ASC);";  
		
		return cad;
	}

	/* (non-Javadoc)
	 * @see edu.acatlan.unam.shared.bdoo.ElementoGrafico#getPosX()
	 */
	public int getPosX() {
		return posX.intValue();
	}
	
	/* (non-Javadoc)
	 * @see edu.acatlan.unam.shared.bdoo.ElementoGrafico#getPosY()
	 */
	public int getPosY() {
		return posY.intValue();
	}
	
	/* (non-Javadoc)
	 * @see edu.acatlan.unam.shared.bdoo.ElementoGrafico#setPosicion(java.lang.Integer, java.lang.Integer)
	 */
	public void setPosicion(int cx, int cy) {
		this.posX = cx;
		this.posY = cy;
	}
	
	/**
	 * @return the columnas
	 */
	public ArrayList<TColumna> getColumnas() {
		return columnas;
	}

	/**
	 * @param columnas the columnas to set
	 */
	public void setColumnas(ArrayList<TColumna> columnas) {
		this.columnas = columnas;
	}
	
	/* (non-Javadoc)
	 * @see edu.acatlan.unam.shared.bdoo.ElementoGrafico#estaBajo(int, int)
	 */
	public boolean estaBajo(int mouseX, int mouseY) {
		isSelected = (mouseX >= posX.intValue() && mouseX <= posX.intValue() + 151 &&
				mouseY >= posY.intValue() && mouseY <= posY.intValue() + (columnas.size() + 1)*16) ? 
			true : false;
		
		return isSelected;
	}
	
	/* (non-Javadoc)
	 * @see edu.acatlan.unam.shared.bdoo.ElementoGrafico#dibuja(com.google.gwt.canvas.dom.client.Context2d)
	 */
	public void dibuja(Context2d contexto) {
		//Colocamos el rectángulo de ancho 150, el alto se calcula con: (número de columnas + 1) * 12
		if(isSelected) {
			contexto.setLineWidth(3);
			contexto.strokeRect(posX.intValue() - 1, posY.intValue() - 1, 151, (columnas.size() + 1)*16);
			contexto.setFillStyle(CssColor.make("#F5BCA9"));
			contexto.fillRect(posX.intValue() - 1, posY.intValue() - 1, 151, (columnas.size() + 1)*16);
			contexto.setFillStyle(CssColor.make("#8A0808"));
		} else {
			contexto.setFillStyle(CssColor.make("#A9BCF5"));
			contexto.fillRect(posX.intValue() - 1, posY.intValue() - 1, 151, (columnas.size() + 1)*16);
			contexto.setFillStyle(CssColor.make("#6E6E6E"));
		}
		//Colocamos el título de la tabla con un máximo de 100 pixels
		contexto.setFont("bold 14px sans-serif");
		contexto.fillText(nombreTb, posX.intValue() + 2, posY.intValue() + 12, 150);
		//Colocamos las columnas de la tabla con un máximo de 100 pixels
		contexto.setFillStyle(CssColor.make("#000"));
		contexto.setFont("italic 14px sans-serif");
		for(int i = 0; i < columnas.size(); i++)
			contexto.fillText(columnas.get(i).getNombreCol(), posX.intValue() + 2, posY.intValue() + (i + 2)*12, 150);
	}

	/**
	 * @return the relaciones
	 */
	public ArrayList<TRelacion> getRelaciones() {
		return relaciones;
	}

	/**
	 * @param relaciones the relaciones to set
	 */
	public void setRelaciones(ArrayList<TRelacion> relaciones) {
		this.relaciones = relaciones;
	}
}
